﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Threading.Tasks;
using KL.UFrame.Core.Exception;
using KL.UFrame.Data.Entities;
using KL.UFrame.Data.Models;

namespace KL.UFrame.Data.Business.Impl
{
    public class VenueBusiness : BusinessBase, IVenueBusiness
    {
        public async Task<List<VenueModel>> GetAllVenuesAsync(bool onlyEnabled = true)
        {
            var result = await Db.Venues.Include(a=>a.CreateUser).Include(b=>b.UpdateUser)
                .Where(a => (onlyEnabled && a.Enabled) || !onlyEnabled).OrderBy(a=>a.Name)
                .Select(a => new VenueModel
                {
                    Name = a.Name,
                    Area = a.Area,
                    Capacity = a.Capacity,
                    Enabled = a.Enabled,
                    Id = a.Id,
                    Purpose = a.Purpose,
                    Devices = a.Devices,
                    ImageUrl = a.ImageUrl,
                    FrontImageUrl=a.FrontImageUrl,
                    CreateId = a.CreateId,
                    CreateUser = a.CreateUser.RealName,
                    CreateTime = a.CreateTime,
                    UpdateId=a.UpdateId,
                    UpdateTime = a.UpdateTime,
                    UpdateUser = a.UpdateUser.RealName
                }).ToListAsync();
            return result;
        }

        public async Task<VenueModel> GetVenueAsync(int id)
        {
            var venue = await Db.Venues.SingleOrDefaultAsync(a=>a.Id==id);
            if(venue == null) throw new ResultException(-404,$"编号为{id}的场馆不存在");
            return new VenueModel
            {
                Name=venue.Name,
                Area = venue.Area,
                Capacity = venue.Capacity,
                Enabled = venue.Enabled,
                Id = venue.Id,
                Purpose = venue.Purpose,
                Devices = venue.Devices,
                ImageUrl = venue.ImageUrl,
                 FrontImageUrl = venue.FrontImageUrl
            };
        }

        public async Task<VenueBookModel> GetVenueBookOfThisMonthAsync(int id, int? month = null)
        {
            var venue = await Db.Venues.FindAsync(id);
            if(venue==null) throw  new ResultException(-404, $"编号为{id}的场馆不存在");
            if (month == null) month = GetMonth();

           var result=  await Db.VenueBookRecords.Include(a=>a.Durations)
                .Where(a => a.Month == month && a.VenueId == id)
                .AsNoTracking().ToListAsync();

            var days = result.SelectMany(a => a.Durations).Select(a => new VenueBookDay
            {
                Day = a.Day.ToString("yyyy-MM-dd"),
                BookType = a.Duration.ToString()
            }).GroupBy(a => a.Day).ToDictionary(a => a.Key)
                .Select(a => new VenueBookDay
                {
                    Day = a.Key,
                    BookType = a.Value.Count() > 1 ? "all" : a.Value.First().BookType
                }).ToArray();

            return new VenueBookModel
            {
                VenueId = id,
                Month = month.Value,
                BookDays = days
            };
        }

        public async Task<bool> BookAsync(VenueBookCreateModel model, string userName)
        {
            using (var trans = Db.Database.BeginTransaction())
            {
                var days = model.Days.Select(a => DateTime.Parse(a.Day)).ToArray();

                var month = GetMonth(days[0]);

                var bookedRecords = await Db.VenueBookRecords.Include(a => a.Durations)
                    .Where(a => a.VenueId == model.VenueId && a.Month == month)
                    .SelectMany(a=>a.Durations)
                    .Where(a=>days.Contains(a.Day))
                    .ToListAsync();
                
                foreach (var record in bookedRecords)
                {
                    var newBook = model.Days.Single(a => a.Day == record.Day.ToString("yyyy-MM-dd"));
                    if (newBook.BookType=="all" || newBook.BookType==record.Duration.ToString())
                    {
                        throw new ResultException(-501, $"{newBook.Day}的{GetDayType(newBook.BookType)}已被预定");
                    }
                }

                var newRecord = new VenueBookRecord
                {
                    Month = month,
                    VenueId=model.VenueId,
                    BookName = model.BookName,
                    BookPhone = model.BookPhone,
                    BookReason = model.Reason,
                    BookTime = DateTime.Now,
                    Status =string.IsNullOrEmpty(userName)? VenueBookRecordStatus.New: VenueBookRecordStatus.Pass
                };

                Db.VenueBookRecords.Add(newRecord);
                foreach (var d in model.Days)
                {
                    if (d.BookType == "all" || d.BookType == "am")
                    {
                        Db.VenueBookRecordDurations.Add(new VenueBookRecordDuration
                        {
                            RecordId = newRecord.Id,
                            Day = DateTime.Parse(d.Day),
                            Duration = VenueBookRecordDurationType.am
                        });
                    }

                    if (d.BookType == "all" || d.BookType == "pm")
                    {
                        Db.VenueBookRecordDurations.Add(new VenueBookRecordDuration
                        {
                            RecordId = newRecord.Id,
                            Day = DateTime.Parse(d.Day),
                            Duration = VenueBookRecordDurationType.pm
                        });
                    }
                }
                await Db.SaveChangesAsync();
                trans.Commit();
                return true;
            }
        }
        
        private static string GetDayType(string bookType)
        {
            string dayType;
            switch (bookType)
            {
                case "pm":
                    dayType = "下午";
                    break;
                case "am":
                    dayType = "上午";
                    break;
                default:
                    dayType = "全天";
                    break;
            }
            return dayType;
        }


        private static int GetMonth(DateTime? time=null)
        {
            if(time==null) time=DateTime.Today;
            return time.Value.Year * 100 + time.Value.Month;
        }

        public async Task<List<VenueBookRecordSearchResultModel>> GetVenueBookRecordsAsync(int venueId, string phone,
            DateTime start, DateTime end)
        {
            var query =await Db.VenueBookRecords.Include(a => a.Durations).Include(a => a.Venue)
                .AsNoTracking()
                .Where(a => venueId <= 0 || a.VenueId == venueId)
                .Where(a => string.IsNullOrEmpty(phone) || a.BookPhone == phone)
                .ToListAsync();

            var result = query.Select(r => new VenueBookRecordSearchResultModel
            {
                Id=r.Id,
                VenueId = r.VenueId,
                VenueName = r.Venue.Name,
                BookName = r.BookName,
                BookPhone = r.BookPhone,
                Reason = r.BookReason,
                Capacity = r.Venue.Capacity,
                Devices = r.Venue.Devices,
                Area = r.Venue.Area,
                Purpose = r.Venue.Purpose,
                BookTime = r.BookTime,
                Status = r.Status,
                StatusDescription = r.StatusDescription,
                Days = r.Durations.Where(d => d.Day >= start && d.Day <= end)
                    .Select(d => new VenueBookDay
                    {
                        Day = d.Day.ToString("yyyy-MM-dd"),
                        BookType = d.Duration.ToString()
                    }).ToList()
            }).ToList();
            result = result.Where(a => a.Days.Any()).ToList();
            foreach (var r in result)
            {
                r.Days = r.Days.GroupBy(a => a.Day).ToDictionary(a => a.Key)
                    .Select(a => new VenueBookDay
                    {
                        Day = a.Key,
                        BookType = a.Value.Count() > 1 ? "全天" : (a.Value.First().BookType == "am" ? "上午" : "下午")
                    }).ToList();
            }

            return result;
        }

        public async Task<bool> DeleteVenueAsync(int id)
        {
            var venue = await Db.Venues.FindAsync(id);
            if(venue==null) throw new ResultException(-2,$"编号为{id}的场馆不存在");
            if (venue.Enabled)
            {
                venue.Enabled = false;
                Db.Entry(venue).State= EntityState.Modified;
                return await Db.SaveChangesAsync() > 0;
            }
            return true;
        }

        public async Task<bool> ResumeVenueAsync(int id)
        {
            var venue = await Db.Venues.FindAsync(id);
            if (venue == null) throw new ResultException(-2, $"编号为{id}的场馆不存在");
            if (!venue.Enabled)
            {
                venue.Enabled = true;
                Db.Entry(venue).State = EntityState.Modified;
                return await Db.SaveChangesAsync() > 0;
            }
            return true;
        }

        public async Task<int> UpdateVenueAsync(VenueModel model)
        {
            var venue = await Db.Venues.FindAsync(model.Id);
            if (venue == null) throw new ResultException(-2, $"编号为{model.Id}的场馆不存在");
            venue.Area = model.Area;
            venue.Capacity = model.Capacity;
            venue.Devices = model.Devices;
            if(!string.IsNullOrEmpty(model.ImageUrl)) venue.ImageUrl = model.ImageUrl;
            if (!string.IsNullOrEmpty(model.FrontImageUrl)) venue.FrontImageUrl = model.FrontImageUrl;
            venue.Name = model.Name;
            venue.Purpose = model.Purpose;
            venue.UpdateId = model.UpdateId;
            venue.UpdateTime = model.UpdateTime;
            Db.Entry(venue).State= EntityState.Modified;
            var result = await Db.SaveChangesAsync();
            if (result > 0) return model.Id;
            throw new ResultException(-501,"保存数据失败");
        }

        public async Task<int> CreateVenueAsync(VenueModel model)
        {
            var venue = new Venue
            {
                Area = model.Area,
                Capacity = model.Capacity,
                Devices = model.Devices,
                ImageUrl = model.ImageUrl,
                FrontImageUrl=model.FrontImageUrl,
                Name = model.Name,
                Purpose = model.Purpose,
                CreateTime = model.CreateTime,
                CreateId = model.CreateId
            };

            Db.Entry(venue).State = EntityState.Added;
            var result = await Db.SaveChangesAsync();
            if (result > 0) return venue.Id;
            throw new ResultException(-501, "保存数据失败");
        }

        public async Task<bool> AuditAsync(int enrollId, VenueBookRecordStatus status, string description)
        {
            var record = await Db.VenueBookRecords.FindAsync(enrollId);
            if (record == null) throw new ResultException(-400, $"编号为{enrollId}的预定记录不存在");

            record.Status = status;
            record.StatusDescription = description;

            Db.Entry(record).State = EntityState.Modified;
            return await Db.SaveChangesAsync() > 0;
        }
    }
} 